package com.ice.work.moment.ticket.service.impl;

import cn.hutool.http.ContentType;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.honeybee.cloud.framework.base.exception.business.BaseBizException;
import com.honeybee.cloud.framework.common.enums.DataStatusEnum;
import com.honeybee.cloud.framework.common.http.HttpClient;
import com.honeybee.cloud.framework.common.http.HttpHeaderEnum;
import com.honeybee.cloud.framework.common.page.Page;
import com.honeybee.cloud.framework.common.response.ResponseEntity;
import com.honeybee.cloud.framework.common.utils.ImgUtil;
import com.ice.work.moment.facade.socket.request.PushMessageRequest;
import com.ice.work.moment.facade.ticket.constant.SystemConstant;
import com.ice.work.moment.facade.ticket.constant.TicketUrl;
import com.ice.work.moment.facade.ticket.dto.ConfigDTO;
import com.ice.work.moment.facade.ticket.dto.CookieDTO;
import com.ice.work.moment.facade.ticket.dto.PassengerDTO;
import com.ice.work.moment.facade.ticket.enums.UserAgentEnum;
import com.ice.work.moment.facade.ticket.mapper.ParamConvertMapper;
import com.ice.work.moment.facade.ticket.mapper.ResponseConvertMapper;
import com.ice.work.moment.facade.ticket.model.Cookie;
import com.ice.work.moment.facade.ticket.param.*;
import com.ice.work.moment.facade.ticket.request.*;
import com.ice.work.moment.facade.ticket.response.*;
import com.ice.work.moment.ticket.service.ICookieService;
import com.ice.work.moment.ticket.service.ISocketService;
import com.ice.work.moment.ticket.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.BasicCookieStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;

import static com.ice.work.moment.facade.ticket.enums.TicketBizExceptionEnum.*;


/**
 * @Description
 * @Author DELL
 * @Create 2019-05-16
 * @Since 1.0.0
 */
@Service
@Slf4j
@SuppressWarnings("all")
public class UserServiceImpl implements IUserService {

    @Autowired
    private HttpClient httpClient;

    @Autowired
    private ICookieService cookieService;


    @Autowired
    private ISocketService socketService;

    @Override
    public String login(LoginParam loginParam, boolean qrLogin) throws BaseBizException {
        CookieDTO cookieDTO = cookieService.findByLoginName(loginParam.getUsername());
        BasicCookieStore cookieStore = cookieDTO.getCookieStore();
        initLoginPage(cookieStore);
        ConfigDTO configParam = getLoginConf(cookieStore);
        //已经登录了
        if (configParam.getLogin()) {
            return cookieDTO.getAppKey();
        }
        //检查登录状态
        CheckOnlineStatusResponse response = checkOnlineStatus(cookieStore);
        if (Objects.equals(SystemConstant.SUCCESS_CODE_CHECK_STATUS, response.getCode())) {
            return response.getNewAppKey();
        }
        //密码登录
        if (configParam.getLoginPasswordCode() && !qrLogin) {
            loginByPassword(loginParam, cookieStore);
        }
        //二维码登录
        if (configParam.getUamLogin() && qrLogin) {
            loginByQrCode(cookieStore);
        }

        response = checkOnlineStatus(cookieStore);
        if (!Objects.equals(SystemConstant.SUCCESS_CODE_CHECK_STATUS, response.getCode())) {
            throw new BaseBizException(LOGIN_FAIL_EXP.getParentCode(), LOGIN_FAIL_EXP.getSubCode(), LOGIN_FAIL_EXP.getMessage());
        }

        sendUserLogin(cookieStore);
        sendPassWordRedirect(cookieStore);
        authClient(cookieStore, response);
        InitMyData initMyData = initMyData(cookieStore);
        createCookie(cookieDTO, response, cookieStore, initMyData);
        return response.getNewAppKey();
    }

    @Override
    public void out(CookieDTO cookieDTO) throws BaseBizException {
        //删除数据库信息先
        cookieService.deleteByAppKey(cookieDTO.getAppKey());
        logout(cookieDTO.getCookieStore());
        //检查登录状态
        CheckOnlineStatusResponse response = checkOnlineStatus(cookieDTO.getCookieStore());
        if (Objects.equals(SystemConstant.SUCCESS_CODE_CHECK_STATUS, response.getCode())) {
            throw new BaseBizException(OUT_FAIL_EXP.getParentCode(), OUT_FAIL_EXP.getSubCode(), OUT_FAIL_EXP.getMessage());
        }

    }


    @Override
    public Page<PassengerDTO> queryPassengers(QueryPassengerParam passengerParam, CookieDTO cookieDTO) {
        log.info("开始查询常用联系人信息");
        Map<String, String> header = Maps.newHashMap();
        header.put(HttpHeaderEnum.ACCEPT.value, SystemConstant.ACCEPT);
        header.put(HttpHeaderEnum.LANGUAGE.value, SystemConstant.LANGUAGE);
        header.put(HttpHeaderEnum.REFERER.value, TicketUrl.PASSENGERS_HTML);
        header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
        header.put(HttpHeaderEnum.AGENT.value, UserAgentEnum.AGENT_12306.code);
        header.put(HttpHeaderEnum.ENCODING.value, SystemConstant.ENCODING);
        header.put(HttpHeaderEnum.REQUESTED.value, SystemConstant.REQUESTED);
        header.put(HttpHeaderEnum.ORIGIN.value, TicketUrl.BASE_12306_URL);
        header.put(HttpHeaderEnum.CONNECTION.value, SystemConstant.CONNECTION);
        checkLoginStatus(cookieDTO, header);
        try {

            String result = sendForm(cookieDTO.getCookieStore(), TicketUrl.QUERY_PASSENGERS_URL, header, passengerParam);
            QueryPassengersResponse response = JSONObject.parseObject(result, QueryPassengersResponse.class);
            if (Objects.isNull(response)) {
                throw new BaseBizException(INTT_DATA_EXP.getParentCode(), INTT_DATA_EXP.getSubCode(), INTT_DATA_EXP.getMessage());
            }
            if (CollectionUtils.isEmpty(response.getData())) {
                return ParamConvertMapper.INSTANCE.toDTO(null, passengerParam.getPageIndex(), passengerParam.getPageSize());
            }
            return ParamConvertMapper.INSTANCE.toDTO(response.getData().get(0), passengerParam.getPageIndex());
        } catch (Exception e) {
            log.error("查询常用联系人信息异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    private CookieDTO viewPassengersHtml(String appKey) {
        CookieDTO cookieStore = cookieService.findByAppKey(appKey);
        log.info("开始初始化联系人查询页面");
        try {
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.ACCEPT.value, SystemConstant.ACCEPT);
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.LOGOUT_HTML);
            header.put(HttpHeaderEnum.REQUESTED.value, SystemConstant.REQUESTED);
            header.put(HttpHeaderEnum.LANGUAGE.value, SystemConstant.LANGUAGE);
            header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
            header.put(HttpHeaderEnum.ENCODING.value, SystemConstant.ENCODING);
            header.put(HttpHeaderEnum.AGENT.value, UserAgentEnum.AGENT_12306.code);
            header.put(HttpHeaderEnum.ORIGIN.value, TicketUrl.BASE_12306_URL);
            header.put(HttpHeaderEnum.CONNECTION.value, SystemConstant.CONNECTION);
            sendPage(cookieStore.getCookieStore(), TicketUrl.PASSENGERS_HTML, header);
            return cookieStore;
        } catch (Exception e) {
            log.error("初始化联系人查询页面异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    /**
     * 检查登录状态
     *
     * @param cookieDTO
     * @param header
     * @return
     */
    private void checkLoginStatus(CookieDTO cookieDTO, Map<String, String> header) {
        ConfigDTO response = getLoginConf(cookieDTO.getCookieStore(), header);
        //已经登录了--获取到用户真实姓名
        if (!response.getLogin()) {
            throw new BaseBizException(LOGIN_FAIL_EXP.getParentCode(), LOGIN_FAIL_EXP.getSubCode(), LOGIN_FAIL_EXP.getMessage());
        }
    }


    /**
     * 获取初始化信息
     *
     * @param cookieStore
     * @return
     */
    private InitMyData initMyData(BasicCookieStore cookieStore) {
        log.info("开始获取初始化信息");
        try {
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.ACCEPT.value, "*/*");
            header.put(HttpHeaderEnum.LANGUAGE.value, "zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3");
            header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.VIEW_INDEX_URL);
            header.put(HttpHeaderEnum.AGENT.value, UserAgentEnum.AGENT_12306.code);
            header.put(HttpHeaderEnum.ENCODING.value, "gzip, deflate");
            String result = sendForm(cookieStore, TicketUrl.INIT_DATA_URL, header);
            InitMyDataResponse initMyDataResponse = JSONObject.parseObject(result, InitMyDataResponse.class);
            if (Objects.isNull(initMyDataResponse) || Objects.isNull(initMyDataResponse.getData())) {
                throw new BaseBizException(INTT_DATA_EXP.getParentCode(), INTT_DATA_EXP.getSubCode(), INTT_DATA_EXP.getMessage());
            }
            return initMyDataResponse.getData();
        } catch (Exception e) {
            log.error("获取初始化信息异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    /**
     * 检验客户端
     *
     * @param cookieStore
     * @param response
     * @return
     */
    private String authClient(BasicCookieStore cookieStore, CheckOnlineStatusResponse response) {
        log.info("开始检验客户端");
        try {
            AuthClientRequest authClientRequest = new AuthClientRequest();
            authClientRequest.setTk(response.getNewAppKey());
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.ACCEPT.value, SystemConstant.ACCEPT);
            header.put(HttpHeaderEnum.LANGUAGE.value, SystemConstant.LANGUAGE);
            header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.PASSWORD_URL);
            header.put(HttpHeaderEnum.ENCODING.value, SystemConstant.ENCODING);
            header.put(HttpHeaderEnum.AGENT.value, UserAgentEnum.AGENT_12306.code);
            String result = sendForm(cookieStore, TicketUrl.UAMAUTH_CLIENT_URL, header, authClientRequest);

            return result;
        } catch (Exception e) {
            log.error("检验客户端异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }

    }

    /**
     * 发送密码转发 --不知道有什么用的一次请求
     *
     * @param cookieStore
     */
    private void sendPassWordRedirect(BasicCookieStore cookieStore) {
        log.info("开始发送密码转发");
        try {
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.ACCEPT.value, SystemConstant.ACCEPT);
            header.put(HttpHeaderEnum.ENCODING.value, SystemConstant.ENCODING);
            header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
            header.put(HttpHeaderEnum.LANGUAGE.value, SystemConstant.LANGUAGE);
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.LOGIN_HTML);
            header.put(HttpHeaderEnum.AGENT.value, UserAgentEnum.AGENT_12306.code);
            httpClient.sendPage(cookieStore, TicketUrl.PASSWORD_URL, header);
        } catch (Exception e) {
            log.error("密码转发异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    /**
     * 发送用户登录 --不知道有什么用的一次请求
     *
     * @param cookieStore
     */
    private void sendUserLogin(BasicCookieStore cookieStore) {
        log.info("开始发送用户登录信息");
        try {
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.ACCEPT.value, SystemConstant.ACCEPT);
            header.put(HttpHeaderEnum.ENCODING.value, SystemConstant.ENCODING);
            header.put(HttpHeaderEnum.LANGUAGE.value, SystemConstant.LANGUAGE);
            header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.LOGIN_HTML);
            header.put(HttpHeaderEnum.AGENT.value, UserAgentEnum.AGENT_12306.code);
            //移除
            List<org.apache.http.cookie.Cookie> cookieList = cookieStore.getCookies();
            cookieStore.clear();
            for (org.apache.http.cookie.Cookie cookie : cookieList) {
                if (!org.apache.commons.lang3.StringUtils.equals(cookie.getName(), SystemConstant.UAMTK)) {
                    cookieStore.addCookie(cookie);
                }
            }
            httpClient.sendPage(cookieStore, TicketUrl.USER_LOGIN_URL, header);
        } catch (Exception e) {
            log.error("发送用户登录信息异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    /**
     * 登陆
     *
     * @param cookieStore
     */
    private void logout(BasicCookieStore cookieStore) {
        log.info("开始登出");
        try {
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
            header.put(HttpHeaderEnum.ENCODING.value, SystemConstant.ENCODING);
            header.put(HttpHeaderEnum.LANGUAGE.value, SystemConstant.LANGUAGE);
            header.put(HttpHeaderEnum.ACCEPT.value, SystemConstant.ACCEPT);
            header.put(HttpHeaderEnum.AGENT.value, UserAgentEnum.AGENT_12306.code);
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.LOGOUT_HTML);
            header.put(HttpHeaderEnum.UPGRADE_INSECURE_REQUESTS.value, String.valueOf(1));
            httpClient.sendForm(cookieStore, TicketUrl.USER_LOGOUT_URL, header);
        } catch (BaseBizException e) {
            log.info("登出不需要处理的异常", e);
        } catch (Exception e) {
            log.error("登出异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    /**
     * 保存相关登录 cookie信息
     *
     * @param dto
     * @param response
     * @param cookieStore
     */
    private void createCookie(CookieDTO dto, CheckOnlineStatusResponse response, BasicCookieStore cookieStore, InitMyData initMyData) {
        log.info("开始保存cookie相关信息");
        Cookie cookie = new Cookie();
        cookie.setId(dto.getId());
        cookie.setLoginName(dto.getLoginName());
        if (Objects.nonNull(cookieStore)) {
            cookie.setCookieStore(JSONObject.toJSONString(cookieStore));
        } else {
            cookie.setCookieStore("");
        }
        if (Objects.nonNull(response)) {
            cookie.setAppKey(response.getNewAppKey());
        } else {
            cookie.setAppKey("");
        }
        if (Objects.nonNull(initMyData)) {
            cookie.setUserName(initMyData.getUserName());
            cookie.setEmail(initMyData.getEmail());
        }
        cookie.setCode(dto.getCode());
        cookie.setExpireAt(dto.getExpireAt());
        cookie.setCreateAt(new Date());
        cookie.setDataStatus(DataStatusEnum.VALID.key);
        Boolean isSuccess = cookieService.add(cookie);
        if (!isSuccess) {
            throw new BaseBizException(LOGIN_FAIL_EXP.getParentCode(), LOGIN_FAIL_EXP.getSubCode(), LOGIN_FAIL_EXP.getMessage());
        }
    }

    /**
     * 确认登录状态
     *
     * @param cookieStore
     * @return
     */
    private CheckOnlineStatusResponse checkOnlineStatus(BasicCookieStore cookieStore) {
        log.info("开始检验登录信息");
        try {
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.AGENT.value, UserAgentEnum.AGENT_12306.code);
            header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
            header.put(HttpHeaderEnum.ACCEPT.value, SystemConstant.ACCEPT);
            header.put(HttpHeaderEnum.ENCODING.value, SystemConstant.ENCODING);
            header.put(HttpHeaderEnum.LANGUAGE.value, SystemConstant.LANGUAGE);
            header.put(HttpHeaderEnum.CONNECTION.value, SystemConstant.CONNECTION);
            CheckOnlineRequest request = new CheckOnlineRequest();
            String result = sendForm(cookieStore, TicketUrl.UAMTK_URL, header, request);
            CheckOnlineStatusResponse response = JSONObject.parseObject(result, CheckOnlineStatusResponse.class);
            if (Objects.isNull(response)) {
                throw new BaseBizException(RESPONSE_NULL.getParentCode(), RESPONSE_NULL.getSubCode(), RESPONSE_NULL.getMessage());
            }
            return response;
        } catch (Exception e) {
            log.error("检验登录信息异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    /**
     * 二维码登录
     */
    private void loginByQrCode(BasicCookieStore cookieStore) {
        CreateQrCodeParam qrCodeParam = createQrCode(cookieStore);
        String key;
        int maxTimes = 100;
        int i = 0;
        do {
            key = checkQrCode(qrCodeParam, cookieStore);
            if (StringUtils.isEmpty(key)) {
                delay();
            }
            i++;
        } while (StringUtils.isEmpty(key) && i < maxTimes);

    }


    /**
     * 创建登录二维码
     *
     * @param cookieStore
     * @return
     */
    private CreateQrCodeParam createQrCode(BasicCookieStore cookieStore) {
        log.info("开始创建登录二维码");
        try {
            CreateQrCodeRequest qrCodeRequest = new CreateQrCodeRequest();
            String result = sendForm(cookieStore, TicketUrl.CREATE_QR_URL, null, qrCodeRequest);
            CreateQrCodeResponse response = JSONObject.parseObject(result, CreateQrCodeResponse.class);
            CreateQrCodeParam param = ResponseConvertMapper.INSTANCE.toParam(response);
            if (!param.getSuccess()) {
                throw new BaseBizException(CREATE_QC_CODE_EXP.getParentCode(), CREATE_QC_CODE_EXP.getSubCode(), CREATE_QC_CODE_EXP.getMessage());
            }
            String filePath = System.getProperty("java.io.tmpdir") + param.getId() + ".jpg";
            log.info("二维码路径:{}", filePath);
            Boolean isSuccess = ImgUtil.base64ToImage(param.getImage(), filePath);
            if (!isSuccess) {
                throw new BaseBizException(CREATE_QC_CODE_EXP.getParentCode(), CREATE_QC_CODE_EXP.getSubCode(), CREATE_QC_CODE_EXP.getMessage());
            }
            return param;
        } catch (Exception e) {
            log.error("创建登录二维码异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    /**
     * 查询扫码结果
     *
     * @param param
     * @param cookieStore
     * @return
     */
    private String checkQrCode(CreateQrCodeParam param, BasicCookieStore cookieStore) {
        log.info("开始查询扫码结果");
        try {
            CheckQrCodeParam checkQrCodeParam = new CheckQrCodeParam();
            checkQrCodeParam.setUuid(param.getId());
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.LOGIN_HTML);
            header.put(HttpHeaderEnum.ORIGIN.value, TicketUrl.BASE_12306_URL);
            header.put(HttpHeaderEnum.CONTENT_TYPE.value, ContentType.FORM_URLENCODED.toString());
            String result = sendForm(cookieStore, TicketUrl.CHECK_QR_URL, header, checkQrCodeParam);
            CheckQrCodeResponse response = JSONObject.parseObject(result, CheckQrCodeResponse.class);
            if (Objects.equals(SystemConstant.SUCCESS_CODE_CHECK_QR_CODE, response.getCode())) {
                return response.getKey();
            }
            if (Objects.equals(SystemConstant.EXPIRE_CODE_QR_CODE, response.getCode())) {
                throw new BaseBizException(EXPIRE_QC_CODE_EXP.getParentCode(), EXPIRE_QC_CODE_EXP.getSubCode(), EXPIRE_QC_CODE_EXP.getMessage());
            }
            return null;
        } catch (Exception e) {
            log.error("查询扫码结果异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }


    /**
     * 密码登录
     *
     * @param loginParam
     * @param cookieStore
     */
    private void loginByPassword(LoginParam loginParam, BasicCookieStore cookieStore) {
        String captchaImage = getCaptchaImage(cookieStore);
        String check = getCheck(captchaImage);
        String position = autoCheckImage(check, captchaImage);
        checkPosition(cookieStore, position);
        loginParam.setAnswer(position);
        checkPassword(loginParam, cookieStore);
    }

    /**
     * 检验登录密码
     *
     * @param loginParam
     * @param cookieStore
     */
    private void checkPassword(LoginParam loginParam, BasicCookieStore cookieStore) {
        log.info("开始使用密码登录");
        try {
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
            header.put(HttpHeaderEnum.ORIGIN.value, TicketUrl.BASE_12306_URL);
            header.put(HttpHeaderEnum.CONNECTION.value, SystemConstant.CONNECTION);
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.LOGIN_HTML);
            header.put(HttpHeaderEnum.CONTENT_TYPE.value, ContentType.FORM_URLENCODED.toString());
            header.put(HttpHeaderEnum.AGENT.value, UserAgentEnum.AGENT_12306.code);
            header.put(HttpHeaderEnum.ACCEPT.value, SystemConstant.ACCEPT);
            header.put(HttpHeaderEnum.ENCODING.value, SystemConstant.ENCODING);
            header.put(HttpHeaderEnum.LANGUAGE.value, SystemConstant.LANGUAGE);
            String result = sendForm(cookieStore, TicketUrl.LOGIN_URL, header, loginParam);
        } catch (Exception e) {
            log.error("检验登录密码异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());

        }
    }

    /**
     * 自动验证验证码
     *
     * @param cookieStore
     * @param position
     * @return
     */
    private void checkPosition(BasicCookieStore cookieStore, String position) {
        log.info("开始校验验证码内容");
        try {
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
            header.put(HttpHeaderEnum.ORIGIN.value, TicketUrl.BASE_12306_URL);
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.QUERY_INIT_PAGE);
            String url = String.format(TicketUrl.CHECK_CAPTCHA_URL, position, Math.random());
            String result = sendForm(cookieStore, url, header);
            result = result.replaceAll(".+\\(", "").replaceAll("\\);", "");
            CheckPositionResponse response = JSONObject.parseObject(result, CheckPositionResponse.class);
            if (!Objects.equals(SystemConstant.SUCCESS_CODE_CHECK_POSITION, response.getCode())) {
                throw new BaseBizException(CHECK_POSITION_EXP.getParentCode(), CHECK_POSITION_EXP.getSubCode(), CHECK_POSITION_EXP.getMessage());
            }
        } catch (Exception e) {
            log.error("检验验证码异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    /**
     * 自动打码
     *
     * @param check
     * @param image
     * @return
     */
    private String autoCheckImage(String check, String image) {
        log.info("开始自动识别验证码");
        try {
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.HOST_360_URL);
            header.put(HttpHeaderEnum.AGENT.value, UserAgentEnum.AGENT_360.code);
            header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_360_URL);
            CheckImageRequest checkImageRequest = new CheckImageRequest();
            checkImageRequest.setCheck(check);
            checkImageRequest.setImgBuf(image);
            String result = sendJson(TicketUrl.POSITION_URL, JSONObject.toJSONString(checkImageRequest), header);
            CheckImageResponse response = JSONObject.parseObject(result, CheckImageResponse.class);
            if (Objects.isNull(response) || StringUtils.isEmpty(response.getRes())) {
                throw new BaseBizException(IMAGE_CHECK_EXP.getParentCode(), IMAGE_CHECK_EXP.getSubCode(), IMAGE_CHECK_EXP.getMessage());
            }
            return response.getRes().replaceAll("\\(", "").replaceAll("\\)", "");
        } catch (Exception e) {
            log.error("自动识别验证码异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    private String getCheck(String msg) {
        try {
            PushMessageRequest pushMessageRequest = new PushMessageRequest();
            pushMessageRequest.setMessage(msg);
            ResponseEntity<String> result = socketService.pushMessage(pushMessageRequest);
            return result.getData();
        } catch (Exception e) {
            log.error("自动识别验证码异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    /**
     * 识别图片
     *
     * @param image
     * @return
     */
    @Deprecated
    private String identification(String image) {
        log.info("开始检验验证码内容");
        CheckBaseRequest request = new CheckBaseRequest();
        request.setImage(image);
        try {
            String result = sendJson(TicketUrl.CHECK_BASE64_URL, JSONObject.toJSONString(request), null);
            CheckBaseResponse response = JSONObject.parseObject(result, CheckBaseResponse.class);
            if (!response.getSuccess()) {
                throw new BaseBizException(RESPONSE_NULL.getParentCode(), RESPONSE_NULL.getSubCode(), RESPONSE_NULL.getMessage());
            }
            return response.getData().getCheck();
        } catch (Exception e) {
            log.error("检验验证码内容异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    private String sendJson(String url, String params, Map<String, String> header) throws Exception {
        String result = httpClient.sendJson(url, header, params);
        checkResponse(result);
        return result;
    }

    /**
     * 获取验证码
     *
     * @param cookieStore
     * @return
     */
    private String getCaptchaImage(BasicCookieStore cookieStore) {
        log.info("开始获取登录验证码");
        try {
            Long random = System.currentTimeMillis();
            Map<String, String> header = Maps.newHashMap();

            header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
            header.put(HttpHeaderEnum.ORIGIN.value, TicketUrl.BASE_12306_URL);
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.QUERY_INIT_PAGE);

            String url = String.format(TicketUrl.CAPTCHA_IMAGE_URL, System.currentTimeMillis(), random);
            String result = sendForm(cookieStore, url, header);
            result = result.replaceAll(".+\\(", "").replaceAll("\\);", "");
            CaptchaResponse response = JSONObject.parseObject(result, CaptchaResponse.class);
            if (Objects.isNull(response)) {
                throw new BaseBizException(RESPONSE_NULL.getParentCode(), RESPONSE_NULL.getSubCode(), RESPONSE_NULL.getMessage());
            }
            CaptchaParam param = ResponseConvertMapper.INSTANCE.toParam(response);
            if (!param.getSuccess()) {
                throw new BaseBizException(RESPONSE_NULL.getParentCode(), RESPONSE_NULL.getSubCode(), RESPONSE_NULL.getMessage());
            }
            return param.getImage();
        } catch (Exception e) {
            log.error("获取登录验证码异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }

    }

    /**
     * 初始化登录页
     *
     * @return
     */
    private void initLoginPage(BasicCookieStore cookieStore) {
        log.info("开始初始化登录页面");
        try {
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.AGENT.value, UserAgentEnum.AGENT_12306.code);
            header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.INDEX_INIT_URL);
            sendPage(cookieStore, TicketUrl.LOGIN_INIT_PAGE, header);
        } catch (Exception e) {
            log.error("初始化登录页面异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    private String sendForm(BasicCookieStore cookieStore, String url, Map<String, String> header, Object params) throws Exception {
        String result = httpClient.sendForm(cookieStore, url, params, header);
        checkResponse(result);
        return result;
    }

    private void checkResponse(String result) {
        Optional<String> optional = Optional.ofNullable(result);
        if (!optional.isPresent()) {
            throw new BaseBizException(RESPONSE_NULL.getParentCode(), RESPONSE_NULL.getSubCode(), RESPONSE_NULL.getMessage());
        }
    }


    private String sendForm(BasicCookieStore cookieStore, String url, Map<String, String> header) throws Exception {
        return sendForm(cookieStore, url, header, null);
    }

    private String sendPage(BasicCookieStore cookieStore, String url, Map<String, String> header) throws Exception {
        return httpClient.sendPage(cookieStore, url, null, header);
    }

    /**
     * 获取登录配置
     *
     * @param cookieStore
     */
    private ConfigDTO getLoginConf(BasicCookieStore cookieStore) {
        return getLoginConf(cookieStore, null);
    }

    /**
     * 获取登录配置
     *
     * @param cookieStore
     */
    private ConfigDTO getLoginConf(BasicCookieStore cookieStore, Map<String, String> header) {
        log.info("开始获取登录配置");
        try {
            if (Objects.isNull(header)) {
                header = Maps.newHashMap();
                header.put(HttpHeaderEnum.HOST.value, TicketUrl.HOST_12306_URL);
                header.put(HttpHeaderEnum.ORIGIN.value, TicketUrl.BASE_12306_URL);
                header.put(HttpHeaderEnum.REFERER.value, TicketUrl.LOGIN_HTML);
                header.put(HttpHeaderEnum.AGENT.value, UserAgentEnum.AGENT_12306.code);
            }

            String result = sendForm(cookieStore, TicketUrl.CONF_URL, header);
            CheckConfigResponse response = JSONObject.parseObject(result, CheckConfigResponse.class);
            if (Objects.isNull(response) || Objects.isNull(response.getData())) {
                throw new BaseBizException(RESPONSE_NULL.getParentCode(), RESPONSE_NULL.getSubCode(), RESPONSE_NULL.getMessage());
            }
            return ResponseConvertMapper.INSTANCE.toParam(response.getData());
        } catch (Exception e) {
            log.error("获取登录配置异常", e);
            throw new BaseBizException(REQUEST_EXP.getParentCode(), REQUEST_EXP.getSubCode(), REQUEST_EXP.getMessage());
        }
    }

    private void delay() {
        try {
            Thread.sleep(5000);
        } catch (Exception e) {
            log.debug("延迟异常", e);
        }

    }

}
